package com.archerdu.commons.util;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Random;

import javax.imageio.ImageIO;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

/**
 * 图片工具类
 * 
 * @projectName springDemo
 * @description 图片工具类
 * @author archer du
 * @createDate 2013年9月27日 下午5:20:53
 * @updateUser dxf
 * @updateDate 2013年9月27日 下午5:20:53
 * @updateRemark 新建
 * @version 0.0.1
 */
@SuppressWarnings("restriction")
public class ImgUtil {

    private static final Log    LOG                 = LogFactory.getLog(ImgUtil.class);
    private static final String PICTRUE_FORMATE_JPG = "jpg";
    public static final String  FONT_FAMILY         = "宋体";
    public static final Integer FONT_SIZE           = 16;

    public static void main(String[] args) {
        // ImgTool.pressImage("E:/360Downloads/test2.gif",
        // "E:/360Downloads/test2_s.gif", 10, 10, 0.4F);
        ImgUtil.pressText("E:/360Downloads/test2.gif", "透明水印", ImgUtil.FONT_FAMILY, 1, FONT_SIZE,
                CaptchaCode.getRandColor(200, 250), 10, 10, 0.7F);
    }

    /**
     * 按比例压缩图片
     * 
     * @param src
     * @param tar
     * @param width
     * @param height
     * @param proportion
     *            是否等比缩放
     */
    public static void compress(String src, String tar, int width, int height, boolean proportion, boolean magnify) {
        try {
            InputStream input = new FileInputStream(src);
            OutputStream out = new FileOutputStream(tar);
            compress(input, out, width, height, proportion, magnify);
        } catch (FileNotFoundException e) {
            LOG.error(e.getMessage(), e);
        }
    }

    /**
     * 压缩图片
     * 
     * @param input
     * @param output
     * @param width
     * @param height
     * @param proportion
     *            是否等比缩放
     */
    public static void compress(InputStream input, OutputStream out, int width, int height, boolean proportion,
            boolean magnify) {
        width = width > 0 ? width : 100;
        height = height > 0 ? height : 100;
        try {
            Image img = ImageIO.read(input);
            int imgWidth = img.getWidth(null);
            int imgHeight = img.getHeight(null);
            // 如果不需要放大并且图片大小小于缩放比例，则不缩放
            if (!magnify && imgWidth <= width && imgHeight <= height) {
                width = imgWidth;
                height = imgHeight;
            } else if (proportion) {
                // 等比缩放
                // 分别计算宽和高的缩放比例
                double rate1 = ((double) imgWidth) / (double) width + 0.1;
                double rate2 = ((double) imgHeight) / (double) height + 0.1;
                // 取宽和高的最大缩放比例
                double rate = rate1 > rate2 ? rate1 : rate2;
                width = (int) (((double) imgWidth) / rate);
                height = (int) (((double) imgHeight) / rate);
            }
            // 缩放图片
            BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            // 采用平滑模式缩放
            tag.getGraphics().drawImage(img.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);
            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
            encoder.encode(tag);

            out.close();
            input.close();
            out.close();
        } catch (IOException e) {
            LOG.error(e.getMessage(), e);
        }
    }

    /**
     * 文字变图片
     * 
     * @param str
     * @param width
     * @param height
     * @param out
     */
    public static void string2Image(String str, int width, int height, OutputStream out) {
        // 防止非负数
        width = width > 0 ? width : 60;
        height = height > 0 ? height : 18;
        // 生成一张新图片
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Font font = new Font(FONT_FAMILY, Font.BOLD, FONT_SIZE);
        // 绘制图片
        Random random = new Random();
        Graphics g = image.getGraphics();
        g.setColor(CaptchaCode.getRandColor(200, 250));
        g.fillRect(1, 1, width - 1, height - 1);
        g.setColor(CaptchaCode.getRandColor(160, 200));
        g.drawRect(0, 0, width - 1, height - 1);
        // 随机生成线条，让图片看起来更加杂乱
        for (int i = 0; i < 100; i++) {
            int x = random.nextInt(width - 1);
            int y = random.nextInt(height - 1);
            int x1 = random.nextInt(6) + 1;
            int y1 = random.nextInt(12) + 1;
            g.drawLine(x, y, x + x1, y + y1);
        }
        g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
        g.setFont(font);
        g.drawString(str, FONT_SIZE + 10, FONT_SIZE);
        g.dispose();
        try {
            ImageIO.write(image, "JPEG", out);
            out.close();
        } catch (IOException e) {
            LOG.error(e.getMessage(), e);
        }
    }

    /**
     * 添加图片水印
     * 
     * @param targetImg
     *            目标图片路径，如：C://myPictrue//1.jpg
     * @param waterImg
     *            水印图片路径，如：C://myPictrue//logo.png
     * @param x
     *            水印图片距离目标图片左侧的偏移量，如果x<0, 则在正中间
     * @param y
     *            水印图片距离目标图片上侧的偏移量，如果y<0, 则在正中间
     * @param alpha
     *            透明度(0.0 -- 1.0, 0.0为完全透明，1.0为完全不透明)
     */
    public final static void pressImage(String targetImg, String waterImg, int x, int y, float alpha) {
        try {
            File file = new File(targetImg);
            Image image = ImageIO.read(file);
            int width = image.getWidth(null);
            int height = image.getHeight(null);
            BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = bufferedImage.createGraphics();
            g.drawImage(image, 0, 0, width, height, null);

            Image waterImage = ImageIO.read(new File(waterImg)); // 水印文件
            int width_1 = waterImage.getWidth(null);
            int height_1 = waterImage.getHeight(null);
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));

            int widthDiff = width - width_1;
            int heightDiff = height - height_1;
            if (x < 0) {
                x = widthDiff / 2;
            } else if (x > widthDiff) {
                x = widthDiff;
            }
            if (y < 0) {
                y = heightDiff / 2;
            } else if (y > heightDiff) {
                y = heightDiff;
            }
            g.drawImage(waterImage, x, y, width_1, height_1, null); // 水印文件结束
            g.dispose();
            ImageIO.write(bufferedImage, PICTRUE_FORMATE_JPG, file);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 添加文字水印
     * 
     * @param targetImg
     *            目标图片路径，如：C://myPictrue//1.jpg
     * @param pressText
     *            水印文字， 如：中国证券网
     * @param fontName
     *            字体名称， 如：宋体
     * @param fontStyle
     *            字体样式，如：粗体和斜体(Font.BOLD|Font.ITALIC)
     * @param fontSize
     *            字体大小，单位为像素
     * @param color
     *            字体颜色
     * @param x
     *            水印文字距离目标图片左侧的偏移量，如果x<0, 则在正中间
     * @param y
     *            水印文字距离目标图片上侧的偏移量，如果y<0, 则在正中间
     * @param alpha
     *            透明度(0.0 -- 1.0, 0.0为完全透明，1.0为完全不透明)
     */
    public static void pressText(String targetImg, String pressText, String fontName, int fontStyle, int fontSize,
            Color color, int x, int y, float alpha) {
        try {
            File file = new File(targetImg);

            Image image = ImageIO.read(file);
            int width = image.getWidth(null);
            int height = image.getHeight(null);
            BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = bufferedImage.createGraphics();
            g.drawImage(image, 0, 0, width, height, null);
            g.setFont(new Font(fontName, fontStyle, fontSize));
            g.setColor(color);
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));

            int width_1 = fontSize * getLength(pressText);
            int height_1 = fontSize;
            int widthDiff = width - width_1;
            int heightDiff = height - height_1;
            if (x < 0) {
                x = widthDiff / 2;
            } else if (x > widthDiff) {
                x = widthDiff;
            }
            if (y < 0) {
                y = heightDiff / 2;
            } else if (y > heightDiff) {
                y = heightDiff;
            }

            g.drawString(pressText, x, y + height_1);
            g.dispose();
            ImageIO.write(bufferedImage, PICTRUE_FORMATE_JPG, file);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取字符长度，一个汉字作为 1 个字符, 一个英文字母作为 0.5 个字符
     * 
     * @param text
     * @return 字符长度，如：text="中国",返回 2；text="test",返回 2；text="中国ABC",返回 4.
     */
    public static int getLength(String text) {
        int textLength = text.length();
        int length = textLength;
        for (int i = 0; i < textLength; i++) {
            if (String.valueOf(text.charAt(i)).getBytes().length > 1) {
                length++;
            }
        }
        return (length % 2 == 0) ? length / 2 : length / 2 + 1;
    }

}
